package com.xu.cloud.common.idempotent.support;

import com.xu.cloud.common.constant.CryptConstant;
import com.xu.cloud.common.exception.ErrorCodeEnum;
import com.xu.cloud.common.idempotent.IdempotentIfc;
import com.xu.cloud.common.idempotent.IdempotentProperties;
import com.xu.cloud.common.sequence.ISequence;
import com.xu.cloud.common.sequence.wrapper.DateTimeFormatSequenceWrapper;
import com.xu.cloud.common.util.AssertUtil;
import com.xu.cloud.common.util.MessageDigestUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * map内存幂等实现
 *
 * @author xuguan
 * @since 2025/3/18
 */
@Slf4j
public class MapIdempotent implements IdempotentIfc {
    private final ISequence sequence;
    private final IdempotentProperties properties;
    private Map<String, String> map;

    public MapIdempotent(ISequence sequence,
                         IdempotentProperties properties) {
        this.sequence = sequence;
        this.properties = properties;
        map = new ConcurrentHashMap<>();
    }

    @Override
    public String createIdempotentToken() {
        String id;
        if (sequence instanceof DateTimeFormatSequenceWrapper) {
            id = sequence.nextId();
        } else {
            id = new DateTimeFormatSequenceWrapper(sequence).nextId();
        }
        final String idempotentToken = MessageDigestUtil.encryptToHex(id, CryptConstant.MD5_DIGEST_ALGORITHM);
        final String key = properties.getPrefix() + idempotentToken;
        map.put(key, id);
        log.info("创建幂等token完成, idempotentToken={}", idempotentToken);
        return idempotentToken;
    }

    @Override
    public boolean checkIdempotentToken(String token) {
        AssertUtil.assertHasText(token);
        final String key = properties.getPrefix() + token;
        final String v = map.get(key);
        AssertUtil.assertHasText(v, ErrorCodeEnum.ERR_REQUEST_REPEAT.info().newException());
        log.info("幂等校验通过");
        return true;
    }

    @Override
    public void postProcess(String token) {
        final String key = properties.getPrefix() + token;
        map.remove(key);
        log.info("删除幂等token成功");
    }
}
